///////////////////////////////////////////////////////////////////////////////////////////////////
/// \file formic/fqmc/rgp_detail.h
///
/// \brief   header file for some functions used with the restricted geminal power
///
///////////////////////////////////////////////////////////////////////////////////////////////////

#ifndef FORMIC_FQMC_RGP_DETAIL_HEADER
#define FORMIC_FQMC_RGP_DETAIL_HEADER

namespace formic {

  template <class S> class Hamiltonian;

  namespace fqmc {

    template <class S> S rgp_single_ratio(const int n,
                                          const S d1,
                                          const S * const v1,
                                          const S * const u1,
                                          const S * const i1,
                                                S * const w);

    template <class S> S rgp_double_ratio(const int n,
                                          const S d1,
                                          const S d2,
                                          const S * const v1,
                                          const S * const v2,
                                          const S * const u1,
                                          const S * const u2,
                                          const S * const i1,
                                          const S * const i2,
                                                S * const w);

    template <class S> void rgp_build_occupied_matrix(const int nap,
                                                      const int nas,
                                                      const S * const gamma,
                                                      const int * const a_sites,
                                                      const int * const b_sites,
                                                      S * const mat);

    template <class S> void rgp_row_diff(const int nap,
                                         const int nas,
                                         const int new_row,
                                         const int old_row,
                                         const S * const gamma,
                                         const int * const b_sites,
                                         S * const diff);

    template <class S> void rgp_col_diff(const int nap,
                                         const int nas,
                                         const int new_col,
                                         const int old_col,
                                         const S * const gamma,
                                         const int * const a_sites,
                                         S * const diff);

    template <class S> void rgp_row_update(const int nap,
                                           const int nas,
                                           const int new_occ_site,
                                           const int old_occ_site,
                                           const S * const gamma,
                                           const int * const a_site_to_occ,
                                           const int * const a_occ_to_site,
                                           const int * const b_occ_to_site,
                                           S * const occ_mat,
                                           S * const inv_mat,
                                           S * const wv1,
                                           S * const wv2,
                                           S * const wv3);

    template <class S> void rgp_col_update(const int nap,
                                           const int nas,
                                           const int new_occ_site,
                                           const int old_occ_site,
                                           const S * const gamma,
                                           const int * const b_site_to_occ,
                                           const int * const b_occ_to_site,
                                           const int * const a_occ_to_site,
                                           S * const occ_mat,
                                           S * const inv_mat,
                                           S * const wv1,
                                           S * const wv2,
                                           S * const wv3);

    template <class S> S rgp_det_ratio_deriv(const int nap,
                                             const int nas,
                                             const int nds,
                                             const int * const newly_occ,
                                             const int * const newly_emp,
                                             const S * const gamma,
                                             const S * const inv_mat,
                                             const S * const der_coeff,
                                             const S * const cont_inv,
                                             const int * const a_occ_to_site,
                                             const int * const b_occ_to_site,
                                             const int * const a_site_to_occ,
                                             const int * const b_site_to_occ,
                                             S * const work);

    template <class S> S rgp_det_ratio(const int nap,
                                       const int nas,
                                       const int nds,
                                       const int * const newly_occ,
                                       const int * const newly_emp,
                                       const S * const gamma,
                                       const S * const inv_mat,
                                       const int * const a_occ_to_site,
                                       const int * const b_occ_to_site,
                                       const int * const a_site_to_occ,
                                       const int * const b_site_to_occ,
                                       S * const wv1,
                                       S * const wv2,
                                       S * const wv3);

    template <class S> S rgp_simple_local_energy(const int nap,
                                                 const int nas,
                                                 const formic::Hamiltonian<S> & ham,
                                                 const S * const gamma,
                                                 const S * const inv_mat,
                                                 const S * const der_coeff,
                                                 const S * const cont_inv,
                                                 const int * const a_occ_to_site,
                                                 const int * const b_occ_to_site,
                                                 const int * const a_site_to_occ,
                                                 const int * const b_site_to_occ,
                                                 const int * const a_unocc_to_site,
                                                 const int * const b_unocc_to_site,
                                                 const int * const a_site_to_unocc,
                                                 const int * const b_site_to_unocc,
                                                 S * const work);

  }

}

#endif
